package com.mini.grpc.protoc.parser;

import com.mini.grpc.protoc.model.MethodDefinition;
import com.mini.grpc.protoc.model.ServiceDefinition;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 服务解析器
 * 解析proto文件或服务定义，生成ServiceDefinition对象
 * 
 * @author Mini-gRPC
 */
public class ServiceParser {
    
    // 正则表达式模式
    private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([\\w.]+)\\s*;");
    private static final Pattern JAVA_PACKAGE_PATTERN = Pattern.compile("option\\s+java_package\\s*=\\s*\"([^\"]+)\"\\s*;");
    private static final Pattern JAVA_OUTER_CLASSNAME_PATTERN = Pattern.compile("option\\s+java_outer_classname\\s*=\\s*\"([^\"]+)\"\\s*;");
    private static final Pattern SERVICE_PATTERN = Pattern.compile("service\\s+(\\w+)\\s*\\{");
    private static final Pattern RPC_PATTERN = Pattern.compile("rpc\\s+(\\w+)\\s*\\(\\s*(stream\\s+)?(\\w+)\\s*\\)\\s*returns\\s*\\(\\s*(stream\\s+)?(\\w+)\\s*\\)\\s*;");
    private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\s+\"([^\"]+)\"\\s*;");
    
    /**
     * 从输入流解析服务定义
     * 
     * @param inputStream 输入流
     * @return 服务定义列表
     * @throws IOException 如果读取失败
     */
    public List<ServiceDefinition> parseFromInputStream(InputStream inputStream) throws IOException {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            
            StringBuilder content = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line).append('\n');
            }
            
            return parseFromString(content.toString());
        }
    }
    
    /**
     * 从字符串解析服务定义
     * 
     * @param content proto文件内容
     * @return 服务定义列表
     */
    public List<ServiceDefinition> parseFromString(String content) {
        List<ServiceDefinition> services = new ArrayList<>();
        
        // 解析包信息
        String packageName = extractPackageName(content);
        String javaPackage = extractJavaPackage(content);
        String outerClassName = extractJavaOuterClassName(content);
        List<String> imports = extractImports(content);
        
        // 解析服务
        List<String> serviceBlocks = extractServiceBlocks(content);
        for (String serviceBlock : serviceBlocks) {
            ServiceDefinition service = parseService(serviceBlock, packageName, 
                                                   javaPackage, outerClassName, imports);
            if (service != null) {
                services.add(service);
            }
        }
        
        return services;
    }
    
    /**
     * 提取包名
     * 
     * @param content proto文件内容
     * @return 包名
     */
    private String extractPackageName(String content) {
        Matcher matcher = PACKAGE_PATTERN.matcher(content);
        return matcher.find() ? matcher.group(1) : null;
    }
    
    /**
     * 提取Java包名
     * 
     * @param content proto文件内容
     * @return Java包名
     */
    private String extractJavaPackage(String content) {
        Matcher matcher = JAVA_PACKAGE_PATTERN.matcher(content);
        return matcher.find() ? matcher.group(1) : null;
    }
    
    /**
     * 提取Java外部类名
     * 
     * @param content proto文件内容
     * @return Java外部类名
     */
    private String extractJavaOuterClassName(String content) {
        Matcher matcher = JAVA_OUTER_CLASSNAME_PATTERN.matcher(content);
        return matcher.find() ? matcher.group(1) : null;
    }
    
    /**
     * 提取导入列表
     * 
     * @param content proto文件内容
     * @return 导入列表
     */
    private List<String> extractImports(String content) {
        List<String> imports = new ArrayList<>();
        Matcher matcher = IMPORT_PATTERN.matcher(content);
        while (matcher.find()) {
            imports.add(matcher.group(1));
        }
        return imports;
    }
    
    /**
     * 提取服务块
     * 
     * @param content proto文件内容
     * @return 服务块列表
     */
    private List<String> extractServiceBlocks(String content) {
        List<String> serviceBlocks = new ArrayList<>();
        
        int index = 0;
        while (index < content.length()) {
            int serviceStart = content.indexOf("service", index);
            if (serviceStart == -1) {
                break;
            }
            
            int braceStart = content.indexOf('{', serviceStart);
            if (braceStart == -1) {
                break;
            }
            
            int braceEnd = findMatchingBrace(content, braceStart);
            if (braceEnd == -1) {
                break;
            }
            
            String serviceBlock = content.substring(serviceStart, braceEnd + 1);
            serviceBlocks.add(serviceBlock);
            
            index = braceEnd + 1;
        }
        
        return serviceBlocks;
    }
    
    /**
     * 查找匹配的大括号
     * 
     * @param content 内容
     * @param startIndex 开始索引
     * @return 匹配的大括号索引
     */
    private int findMatchingBrace(String content, int startIndex) {
        int braceCount = 1;
        int index = startIndex + 1;
        
        while (index < content.length() && braceCount > 0) {
            char ch = content.charAt(index);
            if (ch == '{') {
                braceCount++;
            } else if (ch == '}') {
                braceCount--;
            }
            index++;
        }
        
        return braceCount == 0 ? index - 1 : -1;
    }
    
    /**
     * 解析单个服务
     * 
     * @param serviceBlock 服务块内容
     * @param packageName 包名
     * @param javaPackage Java包名
     * @param outerClassName 外部类名
     * @param imports 导入列表
     * @return 服务定义
     */
    private ServiceDefinition parseService(String serviceBlock, 
                                         String packageName,
                                         String javaPackage,
                                         String outerClassName,
                                         List<String> imports) {
        
        // 提取服务名
        Matcher serviceMatcher = SERVICE_PATTERN.matcher(serviceBlock);
        if (!serviceMatcher.find()) {
            return null;
        }
        
        String serviceName = serviceMatcher.group(1);
        
        // 解析方法
        List<MethodDefinition> methods = parseRpcMethods(serviceBlock);
        
        return new ServiceDefinition.Builder()
                .setPackageName(packageName)
                .setServiceName(serviceName)
                .setJavaPackage(javaPackage)
                .setOuterClassName(outerClassName)
                .addImport(imports.toString()) // 简化处理
                .build();
    }
    
    /**
     * 解析RPC方法
     * 
     * @param serviceBlock 服务块内容
     * @return 方法定义列表
     */
    private List<MethodDefinition> parseRpcMethods(String serviceBlock) {
        List<MethodDefinition> methods = new ArrayList<>();
        
        Matcher rpcMatcher = RPC_PATTERN.matcher(serviceBlock);
        while (rpcMatcher.find()) {
            String methodName = rpcMatcher.group(1);
            boolean clientStreaming = rpcMatcher.group(2) != null;
            String inputType = rpcMatcher.group(3);
            boolean serverStreaming = rpcMatcher.group(4) != null;
            String outputType = rpcMatcher.group(5);
            
            MethodDefinition method = new MethodDefinition(
                    methodName, inputType, outputType, 
                    clientStreaming, serverStreaming);
            methods.add(method);
        }
        
        return methods;
    }
    
    /**
     * 创建简单的服务定义（用于测试）
     * 
     * @param serviceName 服务名
     * @param packageName 包名
     * @return 服务定义
     */
    public ServiceDefinition createSimpleService(String serviceName, String packageName) {
        // 创建一个简单的Hello方法
        MethodDefinition helloMethod = new MethodDefinition(
                "SayHello", "HelloRequest", "HelloResponse", false, false);
        
        return new ServiceDefinition.Builder()
                .setPackageName(packageName)
                .setServiceName(serviceName)
                .setJavaPackage(packageName)
                .addMethod(helloMethod)
                .build();
    }
    
    /**
     * 创建流式服务定义（用于测试）
     * 
     * @param serviceName 服务名
     * @param packageName 包名
     * @return 服务定义
     */
    public ServiceDefinition createStreamingService(String serviceName, String packageName) {
        List<MethodDefinition> methods = new ArrayList<>();
        
        // 一元调用
        methods.add(new MethodDefinition("SayHello", "HelloRequest", "HelloResponse", false, false));
        
        // 客户端流式调用
        methods.add(new MethodDefinition("RecordRoute", "Point", "RouteSummary", true, false));
        
        // 服务端流式调用
        methods.add(new MethodDefinition("ListFeatures", "Rectangle", "Feature", false, true));
        
        // 双向流式调用
        methods.add(new MethodDefinition("RouteChat", "RouteNote", "RouteNote", true, true));
        
        ServiceDefinition.Builder builder = new ServiceDefinition.Builder()
                .setPackageName(packageName)
                .setServiceName(serviceName)
                .setJavaPackage(packageName);
        
        for (MethodDefinition method : methods) {
            builder.addMethod(method);
        }
        
        return builder.build();
    }
} 